package com.briup.server.config;

import com.briup.server.domain.vo.MenuVO;

import java.util.*;

public class MenuPermissionMerger {

    /**
     * 最终版：合并所有层级权限（一级菜单去重+二级菜单合并+三级按钮合并）
     * @param originalMenus 原查询返回的所有菜单（可能含非一级菜单、重复菜单）
     * @return 合并后的树形菜单（无重复，权限全量）
     */
    public static List<MenuVO> mergeAllLevels(List<MenuVO> originalMenus) {
        if (Objects.isNull(originalMenus) || originalMenus.isEmpty()) {
            return Collections.emptyList();
        }

        // 第一步：只保留一级菜单（type=0）作为根节点，非一级菜单无需作为根节点
        List<MenuVO> rootMenus = originalMenus.stream()
                .filter(menu -> 0 == menu.getType())
                .toList();

        // 第二步：一级菜单按name去重合并，收集所有二级菜单
        Map<String, MenuVO> rootMenuMap = new LinkedHashMap<>(); // 保持菜单顺序
        for (MenuVO root : rootMenus) {
            String rootName = root.getName();
            if (rootMenuMap.containsKey(rootName)) {
                // 已存在该一级菜单，合并其二级菜单
                MenuVO existingRoot = rootMenuMap.get(rootName);
                List<MenuVO> mergedSecondMenus = mergeSecondMenus(
                        existingRoot.getChildren(), root.getChildren()
                );
                existingRoot.setChildren(mergedSecondMenus);
            } else {
                // 不存在，直接添加，同时合并自身二级菜单（避免单个根节点内二级菜单重复）
                List<MenuVO> mergedSecondMenus = mergeSecondMenus(null, root.getChildren());
                root.setChildren(mergedSecondMenus);
                rootMenuMap.put(rootName, root);
            }
        }

        // 第三步：转换为列表，返回最终结果
        return new ArrayList<>(rootMenuMap.values());
    }

    /**
     * 合并二级菜单（按path去重），并合并其三级按钮
     * @param existingSeconds 已存在的二级菜单
     * @param newSeconds 新增的二级菜单
     * @return 合并后的二级菜单列表
     */
    private static List<MenuVO> mergeSecondMenus(List<MenuVO> existingSeconds, List<MenuVO> newSeconds) {
        List<MenuVO> allSeconds = new ArrayList<>();
        if (Objects.nonNull(existingSeconds)) {
            allSeconds.addAll(existingSeconds);
        }
        if (Objects.nonNull(newSeconds)) {
            allSeconds.addAll(newSeconds);
        }

        // 按path分组去重，合并三级按钮
        Map<String, MenuVO> secondMenuMap = new LinkedHashMap<>();
        for (MenuVO second : allSeconds) {
            String secondPath = second.getPath();
            // 处理path为空的情况（用name+type作为唯一标识）
            String key = Objects.isNull(secondPath) || secondPath.isEmpty()
                    ? second.getName() + "_" + second.getType()
                    : secondPath;

            if (secondMenuMap.containsKey(key)) {
                // 已存在该二级菜单，合并其三级按钮
                MenuVO existingSecond = secondMenuMap.get(key);
                List<MenuVO> mergedButtons = mergeThirdButtons(
                        existingSecond.getChildren(), second.getChildren()
                );
                existingSecond.setChildren(mergedButtons);
            } else {
                // 不存在，直接添加，同时合并自身三级按钮
                List<MenuVO> mergedButtons = mergeThirdButtons(null, second.getChildren());
                second.setChildren(mergedButtons);
                secondMenuMap.put(key, second);
            }
        }

        return new ArrayList<>(secondMenuMap.values());
    }

    /**
     * 合并三级按钮（按perms去重）
     * @param existingButtons 已存在的三级按钮
     * @param newButtons 新增的三级按钮
     * @return 合并后的三级按钮列表
     */
    private static List<MenuVO> mergeThirdButtons(List<MenuVO> existingButtons, List<MenuVO> newButtons) {
        List<MenuVO> allButtons = new ArrayList<>();
        if (Objects.nonNull(existingButtons)) {
            allButtons.addAll(existingButtons);
        }
        if (Objects.nonNull(newButtons)) {
            allButtons.addAll(newButtons);
        }

        // 按perms分组去重（perms是权限唯一标识）
        Map<String, MenuVO> buttonMap = new LinkedHashMap<>();
        for (MenuVO button : allButtons) {
            String perms = button.getPerms();
            // 处理perms为空的情况（用name+type作为唯一标识）
            String key = Objects.isNull(perms) || perms.isEmpty()
                    ? button.getName() + "_" + button.getType()
                    : perms;
            buttonMap.putIfAbsent(key, button); // 已存在则不覆盖，保留第一个
        }

        return new ArrayList<>(buttonMap.values());
    }
}